package org.sws.domain.strategy.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.sws.domain.strategy.enums.LogicModel;
import org.sws.domain.strategy.model.entity.RaffleAwardEntity;
import org.sws.domain.strategy.model.entity.RaffleFactorEntity;
import org.sws.domain.strategy.model.entity.StrategyAwardEntity;
import org.sws.domain.strategy.model.valobj.ChainStrategyAwardVO;
import org.sws.domain.strategy.repository.IStrategyRepository;
import org.sws.domain.strategy.service.armory.IStrategyDispatch;
import org.sws.domain.strategy.service.rule.chain.factory.LogicChainFactory;
import org.sws.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import org.sws.types.enums.ResponseCode;
import org.sws.types.exception.AppException;

import java.util.Date;

/**
 * @Author sws
 * @Date 2025/2/17 22:16
 * @description: 抽奖策略抽象类
 */
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy{
    protected IStrategyRepository repository;
    protected IStrategyDispatch strategyDispatch;
    protected LogicChainFactory logicChainFactory;
    protected DefaultTreeFactory defaultTreeFactory;

    protected AbstractRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, LogicChainFactory logicChainFactory, DefaultTreeFactory defaultTreeFactory){
        this.repository = repository;
        this.strategyDispatch = strategyDispatch;
        this.logicChainFactory = logicChainFactory;
        this.defaultTreeFactory = defaultTreeFactory;
    }

    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
        // 1、前置校验
        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if (null == strategyId || StringUtils.isBlank(userId)) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        // 2、抽奖前置过滤 - 责任链抽奖计算【这步拿到的是初步的抽奖ID，之后需要根据ID处理抽奖】注意；黑名单、权重等非默认抽奖的直接返回抽奖结果
        ChainStrategyAwardVO chainStrategyAward = raffleLogicChain(userId, strategyId);
        log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, chainStrategyAward.getAwardId(), chainStrategyAward.getLogicModel());
        if (!LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAward.getLogicModel())) {
            return buildRaffleAwardEntity(strategyId, chainStrategyAward.getAwardId(), chainStrategyAward.getAwardRuleValue());
        }

        // 3、抽奖中、后置过滤 规则树抽奖过滤【奖品ID，会根据抽奖次数判断、库存判断、兜底返回最终的可获得奖品信息】
        DefaultTreeFactory.StrategyAwardData strategyAwardData = raffleLogicTree(userId, strategyId, chainStrategyAward.getAwardId(),raffleFactorEntity.getActivityEndTime());
        // 4、返回抽奖结果
        return buildRaffleAwardEntity(strategyId, strategyAwardData.getAwardId(), strategyAwardData.getAwardRuleValue());

    }
    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId, Integer awardId, String awardConfig) {
        StrategyAwardEntity strategyAward = repository.queryStrategyAwardEntity(strategyId, awardId);
        return RaffleAwardEntity.builder()
                .strategyId(strategyId)
                .awardId(awardId)
                .awardTitle(strategyAward.getAwardTitle())
                .awardConfig(awardConfig)
                .sort(strategyAward.getSort())
                .build();
    }

    /**
     * 前置 策略规则过滤 - 责任链抽奖过滤
     * @param userId 用户ID
     * @param strategyId 策略ID
     * @return 初步奖品结果
     */
    protected abstract ChainStrategyAwardVO raffleLogicChain(String userId, Long strategyId);

    /**
     * 中、后置 奖品规则过滤 - 规则树抽奖过滤
     *
     * @param userId          用户ID
     * @param strategyId      策略ID
     * @param awardId         奖品ID
     * @param activityEndTime 活动结束时间
     * @return 过滤结果【奖品ID，会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】
     */
    protected abstract DefaultTreeFactory.StrategyAwardData raffleLogicTree(String userId, Long strategyId, Integer awardId, Date activityEndTime);



}
